package com.gitee.dupe.file.utils;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.gitee.dolt.utils.DateUtils;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * 视频转码工具类
 *
 * @author jwc
 */
@Component
@Slf4j
public class ConvertVideoUtils {

    @Setter
    private static String ffmpegPath;

    /**
     * 转换视频格式
     *
     * @param sourcePath 输入视频地址
     * @param targetPath 目标视频地址
     * @return
     */
    public static String convert(String sourcePath, String targetPath) {
        if (StrUtil.isEmpty(ffmpegPath)) {
            log.error("ffmpegPath未配置");
            return null;
        }
        File sourceFile = new File(sourcePath);
        if (!FileUtil.isFile(sourceFile)) {
            log.error("文件不存在({})", sourcePath);
            return null;
        }
        log.info("接收到文件({})需要转换", sourceFile.getName());
        long beginTime = System.currentTimeMillis();
        log.info("开始转文件({})", sourcePath);
        String path = process(sourcePath, targetPath);
        if (StrUtil.isNotEmpty(path)) {
            log.info("转换成功");
            long endTime = System.currentTimeMillis();
            long timeCha = (endTime - beginTime);
            String totalTime = DateUtils.zhSumTime(timeCha);
            log.info("转换视频格式共用了:" + totalTime + " ");
        } else {
            log.info("转换失败");
        }
        return path;
    }

    /**
     * 实际转换视频格式的方法
     *
     * @param sourcePath 输入视频地址
     * @param targetPath 目标视频地址
     * @return
     */
    private static String process(String sourcePath, String targetPath) {
        return processVideoFormatH264(sourcePath, targetPath);
    }


    /**
     * 将mpeg4转为h264编码 为了支持播放器
     *
     * @param sourcePath 输入视频地址
     * @param targetPath 目标视频地址
     * @return
     */
    private static String processVideoFormatH264(String sourcePath, String targetPath) {
        List<String> commend = new ArrayList<>();
        commend.add(ffmpegPath);
        commend.add("-i");
        commend.add(sourcePath);
        commend.add("-vcodec");
        commend.add("h264");
        commend.add("-q");
        commend.add("0");
        commend.add("-y");
        commend.add(targetPath);
        try {
            ProcessBuilder builder = new ProcessBuilder();
            builder.command(commend);
            Process p = builder.start();
            doWaitFor(p);
            p.destroy();
            return targetPath;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    private static int doWaitFor(Process p) {
        InputStream in = null;
        InputStream err = null;
        int exitValue = -1;
        try {
            in = p.getInputStream();
            err = p.getErrorStream();
            boolean finished = false;

            while (!finished) {
                try {
                    while (in.available() > 0) {
                        in.read();
                    }
                    while (err.available() > 0) {
                        err.read();
                    }

                    exitValue = p.exitValue();
                    finished = true;

                } catch (IllegalThreadStateException e) {
                    Thread.sleep(500);
                }
            }
        } catch (Exception e) {
            log.error("doWaitFor();: unexpected exception - " + e.getMessage());
        } finally {
            try {
                if (in != null) {
                    in.close();
                }

            } catch (IOException e) {
                log.info(e.getMessage());
            }
            if (err != null) {
                try {
                    err.close();
                } catch (IOException e) {
                    log.info(e.getMessage());
                }
            }
        }
        return exitValue;
    }


}